package cn.sangedon.review.data.spider.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.http.HttpUtil;
import cn.sangedon.review.common.domain.data.RiseLimit;
import cn.sangedon.review.common.domain.data.SpiderMateData;
import cn.sangedon.review.common.service.data.RiseLimitService;
import cn.sangedon.review.common.service.data.TradingDateService;
import cn.sangedon.review.data.constant.SpiderEnum;
import cn.sangedon.review.data.spider.AbstractStockInfoSpider;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 获取东方财富网每日涨停数据
 */
@Slf4j
@Component
public class RiseLimitSpider extends AbstractStockInfoSpider {
    @Autowired
    private RiseLimitService riseLimitService;

    @Autowired
    private TradingDateService tradingDateService;

    @Override
    public void runJob(List<SpiderMateData> spiderMateDataList) {
        spiderMateDataList.stream().filter(e -> e.getSpiderName().equals(SpiderEnum.DC_RISE_HTTP.getName())).findFirst().ifPresent(e -> {
            addSchedule(e);
        });
    }

    @Override
    public void crawlData() {
        crawlData(DateUtil.format(new Date(), "yyyyMMdd"));
    }

    public void crawlData(String crawDate) {
        AtomicInteger index = new AtomicInteger(0);
        while (index.getAndIncrement() < 3 && !processData(crawDate)) {
            log.info("重试{}次获取{}日涨停数据", index.get(), DateUtil.today());
        }
    }

    private boolean processData(String crawDate) {
        try {
            log.info("开始获取{}日涨停", crawDate);
            String latestTradeDate = tradingDateService.getLatestTradingDay(1).get(0);
            long count = riseLimitService.count(new LambdaQueryWrapper<RiseLimit>().eq(RiseLimit::getTradeDate, latestTradeDate));
            if (count > 0) {
                log.info("已获取最新交易日涨停数据,无需重复获取");
                return true;
            }
            String body = HttpUtil.get(super.getSpiderMateData().getSpiderUrl() + crawDate);
            JSONObject retObj = JSONObject.parseObject(body);
            JSONObject riseData = retObj.getJSONObject("data");
            if (riseData == null) {
                log.info("{}日无涨停数据", crawDate);
                return true;
            }
            JSONArray pool = riseData.getJSONArray("pool");
            List<RiseLimit> list = new ArrayList<>();
            for (Object obj : pool) {
                JSONObject data = (JSONObject) obj;
                RiseLimit riseLimit = new RiseLimit();
                riseLimit.setCode(data.getString("c"));
                riseLimit.setName(data.getString("n"));
                riseLimit.setChangeRate(NumberUtil.round(data.getDouble("zdp"), 2).toString());
                Double price = data.getDouble("p") / 1000;
                riseLimit.setCurrentPrice(price.toString());
                riseLimit.setTradingAmount(data.getString("amount"));
                riseLimit.setMarketValue(data.getString("ltsz"));
                riseLimit.setTotalMarketValue(data.getString("tshare"));
                riseLimit.setTurnoverRate(NumberUtil.round(data.getDouble("hs"), 2).toString());
                riseLimit.setCeilFund(data.getString("fund"));
                riseLimit.setFirstLimitTime(data.getString("fbt"));
                riseLimit.setLastLimitTime(data.getString("lbt"));
                riseLimit.setLimitBrokenTimes(data.getInteger("zbc"));
                JSONObject zttj = data.getJSONObject("zttj");
                riseLimit.setLimitStatistics(zttj.getString("ct") + "/" + zttj.getString("days"));
                riseLimit.setLimitContinuousTimes(data.getInteger("lbc"));
                riseLimit.setIndustry(data.getString("hybk"));
                riseLimit.setTradeDate(DateUtil.formatDate(DateUtil.parse(crawDate, "yyyyMMdd")));
                list.add(riseLimit);
            }
            riseLimitService.saveBatch(list);
            log.info("获取{}日涨停数据成功", crawDate);
            return true;
        } catch (Exception e) {
            log.error("{}日获取东方财富涨停板数据失败:{}", DateUtil.today(), e);
            return false;
        }
    }
}
